package com.example.springbootlearn.netty.okhttp;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;
import com.example.springbootlearn.netty.dto.WebSocketInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Dispatcher;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.WebSocket;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @Author：OBM
 * @DATE：2023/11/10 12:48
 */

@Slf4j
@Service
@RequiredArgsConstructor
public class TxAsrWebsocket {

    private static final Map<String, WebSocketInfo> WEB_SOCKET_MAP = new HashMap<>();
    private static final OkHttpClient CLIENT;

    static {
        Dispatcher dispatcher = new Dispatcher();
        dispatcher.setMaxRequests(80);
        CLIENT = new OkHttpClient.Builder().dispatcher(dispatcher).build();
    }

    @Value("${yuyitech.asrserver.url:ws://127.0.0.1:8087/websocket}")
    private String txAsrWsUrl;
    @Value("${yuyitech.asrserver.vadTime:500}")
    private String vadTime;

    public void initAsrWsClient(String sessionId) {
        try {
            String left = getFinalSessionId(sessionId, 0);
            String right = getFinalSessionId(sessionId, 1);
            create(left);
            create(right);
        } catch (Exception e) {
            closeAsrWsClient(sessionId);
            log.error("创建asr连接出错", e);
        }
    }

    public WebSocket create(String sessionId) {
        StringBuilder urlStr = new StringBuilder(txAsrWsUrl);
//                .append("/realtime_asr_ws_private?")
//                .append("&voice_format=1")
//                .append("&needvad=1")
//                .append("&vad_silence_time=").append(vadTime)
//                .append("&voice_id=").append(sessionId);
        Request request = new Request.Builder().url(urlStr.toString()).build();
        log.info("ASR_MMMM voice_id ===>{} create ws url===>{}", sessionId, urlStr);
        WebSocket webSocket = CLIENT.newWebSocket(request, new AsrWebsocketListener(sessionId));
        log.info("ASR_MMMMxxx voice_id ===>{} create ws url===>{}", sessionId, urlStr);
        WEB_SOCKET_MAP.put(sessionId, new WebSocketInfo(webSocket));
        return webSocket;
    }

    /**
     * 只是发送单纯的二进制数据，不需要请求参数
     * 建议每 200ms 发送 200ms 时长（即 1:1 实时率）的数据包，对应 pcm
     * （音频二进制数据）大小为：8k 采样率为 3200 字节，16k 采样率为 6400
     * 字节。
     * 音频发送速率过快超过 1:1 实时率或者音频数据包之间发送间隔超过 6
     * 秒，可能导致引擎出错（跟引擎识别效率相关，一般可以超过 1:1 的实时率），
     * 后台将返回错误并主动断开连接。
     * <p>
     * // 0 市民 LEFT  1 话务员 RIGHT
     *
     * @param sessionId 0 市民 LEFT  1 话务员 RIGHT
     *                  //     * @param role      0 市民 LEFT  1 话务员 RIGHT
     * @param data      采集的数据默认是320字节
     */
    public void sendData(String sessionId, String data) {
        WebSocketInfo webSocketInfo = WEB_SOCKET_MAP.get(sessionId);
        if (webSocketInfo == null) {
            // todo 暂时考虑单机情况
            log.error("找不到连接sessionId = {} 的ASR连接", sessionId);
            return;
        }
        log.info("first send message ===>{}", sessionId);
        if (webSocketInfo.getFirstMessage()) {
            webSocketInfo.setFirstMessage(false);
            ThreadUtil.safeSleep(RandomUtil.randomInt(100, 200));
        } else {
            ThreadUtil.safeSleep(RandomUtil.randomInt(5, 10));
        }
        webSocketInfo.getWebSocket().send(data);
    }

    public void closeAsrWsClient(String sessionId) {
        String left = getFinalSessionId(sessionId, 0);
        String right = getFinalSessionId(sessionId, 1);
        destroy(left);
        destroy(right);
    }

    public void destroy(String sessionId) {
        WebSocketInfo webSocketInfo = WEB_SOCKET_MAP.remove(sessionId);
        if (webSocketInfo != null) {
            log.info("关闭sessionId = {} 的ASR连接", sessionId);
            webSocketInfo.close();
        }
    }

    public void destroyAll() {
        WEB_SOCKET_MAP.forEach((sessionId, webSocketInfo) -> {
            log.info("关闭sessionId = {} 的ASR连接", sessionId);
            webSocketInfo.close();
        });
        WEB_SOCKET_MAP.clear();
    }

    private void close(WebSocket webSocket) {
        if (webSocket != null) {
            webSocket.close(1000, "Connection closed");
        }
    }

    private String getFinalSessionId(String sessionId, int role) {
        return sessionId + "_" + role;
    }

    public void closeByPhone(String caller) {
        Iterator<Map.Entry<String, WebSocketInfo>> iterator = WEB_SOCKET_MAP.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, WebSocketInfo> entry = iterator.next();
            String sessionId = entry.getKey();
            if (sessionId != null && sessionId.startsWith(caller)) {
                iterator.remove();
                WebSocketInfo webSocketInfo = entry.getValue();
                webSocketInfo.close();
            }
        }
    }

//    public void methodCalled(String realSessionId) {
//        long currentTime = System.currentTimeMillis();
//        if (currentTime - lastRecordedTime >= 1000) {
//            log.info("Method calls per second: {} sessionId ={}", callCount, realSessionId);
//            callCount = 1;
//            lastRecordedTime = currentTime;
//        } else {
//            callCount++;
//        }
//    }
}
